#include "LspBuilders.h"

#include <QJsonObject>
#include <QJsonArray>

namespace shell = simodo::shell;
namespace lsp = simodo::lsp;

QVector<shell::Diagnostic> builtDiagnostics(const QJsonArray & diagnostics_array, int & checksum)
{
    QVector<shell::Diagnostic> diagnostics;

    for(auto d_value : diagnostics_array) {
        if (!d_value.isObject())
            continue;
        QJsonObject d_object = d_value.toObject();

        QJsonValue range_value    = d_object["range"];
        QJsonValue severity_value = d_object["severity"];
        QJsonValue message_value  = d_object["message"];

        if (!range_value.isObject() || !severity_value.isDouble() || !message_value.isString())
            continue;

        lsp::Range range = builtRange(range_value.toObject());
        lsp::DiagnosticSeverity severity = static_cast<lsp::DiagnosticSeverity>(severity_value.toInt());
        QString message = message_value.toString().replace("&NewLine;","\n");

        diagnostics.push_back({range,severity,message});

        checksum += range.start().line() + range.start().character() + range.end().line() + range.end().character();
        checksum += static_cast<int>(severity) + message.length();
    }

    return diagnostics;
}

lsp::Position builtPosition(const QJsonObject & position_object)
{
    QJsonValue line_value       = position_object["line"];
    QJsonValue character_value  = position_object["character"];

    if (!line_value.isDouble() || !character_value.isDouble())
        return {};

    return {simodo::inout::position_line_t(line_value.toInt()), simodo::inout::position_character_t(character_value.toInt())};
}

lsp::Range builtRange(const QJsonObject & range_object)
{
    QJsonValue start_value = range_object["start"];
    QJsonValue end_value   = range_object["end"];

    if (!start_value.isObject() || !end_value.isObject())
        return {};

    lsp::Position start = builtPosition(start_value.toObject());
    lsp::Position end   = builtPosition(end_value.toObject());

    if (start > end)
        end = start;

    return {start, end};
}
